package nl.boelen.game.server.connection;

import java.net.InetAddress;

import nl.boelen.game.net.packet.Packet;
import nl.boelen.game.net.packet.Packet10Join;
import nl.boelen.game.net.packet.Packet11Leave;
import nl.boelen.game.net.packet.Packet12Request;
import nl.boelen.game.net.packet.Packet14CheckConnection;
import nl.boelen.game.net.packet.Packet31Movement;
import nl.boelen.game.net.packet.Packet30Health;
import nl.boelen.game.net.packet.PacketTypes;
import nl.boelen.game.server.entity.PlayerMP;
import nl.boelen.game.server.entity.Players;
import nl.boelen.game.server.gui.ServerGUI;
import nl.boelen.game.utils.Utils;

public class ServerPacketHandler {
    private Players players;
    private ServerTCPSender TCPSender;
    private ServerGUI gui;

    public ServerPacketHandler(ServerGUI gui, Players players, ServerTCPSender TCPSender) {
        this.players = players;
        this.TCPSender = TCPSender;
        this.gui = gui;
    }

    public void parsePacket(byte[] data, InetAddress address, int port) {
        String message = new String(data).trim();
        PacketTypes type = Packet.lookupPacket(message.substring(0, 2));

        switch (type) {
            default:
            case INVALID:
                gui.GUILog("Invalid Package from: " + address);
                break;
            case JOIN: // TCP
                gui.GUILog("Join Package from: " + address);
                handleLogin(new Packet10Join(data), address);
                break;
            case LEAVE: // TCP
                gui.GUILog("Leave Package from: " + address);
                handleDisconnect(new Packet11Leave(data));
                break;
            case PLAYERREQUEST: // TCP
                gui.GUILog("PlayerRequest Package from: " + address);
                handlePlayerRequest(new Packet12Request(data), address, port);
                break;
            case MOVEMENT: // UDP
                handleMovement(new Packet31Movement(data));
                break;
            case CHECKCONNECTION: // TCP
                gui.GUILog("CheckConnection Package from: " + address);
                handleCheckConnection(new Packet14CheckConnection(data));
                break;
            case HEALTH: // TCP
                gui.GUILog("Health Package from: " + address);
                handleHealth(new Packet30Health(data));
                break;
        }
    }

    private void handleLogin(Packet10Join p, InetAddress address) {
        gui.GUILog(p.getUsername() + " has connected");
        PlayerMP player = new PlayerMP(p.getX(), p.getY(), p.getUsername(), address, p.getUDPPort(), p.getTCPPort(), p.getUniqueKey(),
                p.getShirtColor(), p.getMovingDirection(), p.getMaxhp());
        players.addPlayerMP(player, p);
    }

    private void handleDisconnect(Packet11Leave p) {
        gui.GUILog(p.getUsername() + " has disconnected");
        players.removePlayerMP(p);
    }

    private void handlePlayerRequest(Packet12Request p, InetAddress address, int port) {
        PlayerMP player = players.getPlayerMP(p.getFromUniqueKey());
        player.hasChecked();
        PlayerMP reqPlayer = players.getPlayerMP(p.getNeedUniqueKey());

        if (reqPlayer != null) {
            Packet10Join sendpacket = new Packet10Join(reqPlayer.getUserName(), reqPlayer.getUniqueKey(), reqPlayer.getShirtColor(),
                    reqPlayer.getX(), reqPlayer.getY(), reqPlayer.getTCPPort(), reqPlayer.getUDPPort(), reqPlayer.getMovingDirection(),
                    reqPlayer.getMaxhp(), reqPlayer.getHp());
            TCPSender.sendPacket(sendpacket, address, port);
        }
    }

    private void handleMovement(Packet31Movement p) {
        PlayerMP player = players.getPlayerMP(p.getUniqueKey());
        if (player != null) {
            player.hasMoved(p);
            players.sendUDPDataToAllClientsExcept(player, p);
        }
    }

    private void handleCheckConnection(Packet14CheckConnection p) {
        PlayerMP player = players.getPlayerMP(p.getUniqueKey());
        if (player != null) {
            player.checked();
        }
    }

    private void handleHealth(Packet30Health p) {
        PlayerMP player = players.getPlayerMP(p.getUniqueKey());
        if (player != null) {
            player.setHp(p.getHp());
            players.sendTCPDataToAllClientsExcept(player, p);
        }
    }
}
